{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", " César et la brute force\n", "
\n", "

Navigation dans la page

\n", "

\n", " Si c'est votre première visite dans ce TP, lisez attentivement chacun des points détaillé après ce paragraphe.
\n", " Si vous avez déjà commencer à travailler sur ce TP et que vous souhaiter vous déplacer rapidement dans une partie précise vous pouvez choisir la partie que vous souhaitez rejoindre ci-dessous.
\n", "

\n", " Menu de navigation\n", " \n", "
\n", "

\n", "\n", "
\n", " Technologie jupyter\n", "

\n", " La technologie jupyter permet d'exécuter du code python par un simple clique sur Executer ci-dessus.
\n", " Les morceaux de code de cette page sont interprétées case par case. Pour savoir quelle case a été interprétée avant une autre, il suffit de repérer le numéro devant la case.
\n", " Une fois qu'une case a été interprétée (=exécutée), la page garde en mémoire les variables et fonctions lues
\n", " La plateforme propose quelques outils de purge de la mémoire : \n", "

\n", "

\n", "
\n", "

SAUVEGARDER VOTRE TRAVAIL

\n", "

\n", " Pour ne pas perdre votre travail pensez à le sauvegarder régulièrement. Par défault, la sauvegarde par un clic sur la disquette en haut à gauche de page, ou par le racourci clavier classique ctrl+S\n", " est une sauvegarde en local, sur le serveur de jupyter. Vous pouvez et devez très régulièrement sauvegarder votre travail sur votre support personnel de sauvegarde (clef USB, se l'envoyer par mail etc). Ce faisant vous disposerez d'un fichier .ipynb (IPYthon NoteBook) qu'il vous suffira de recharger pour avancer. Après le rechargement assurez vous que les fonctionnalités anciennement developpées et variables utilisées sont bien dans la mémoire de la page (en rééxecutant les cases, ou plus rapidement par Kernel > Restart & Run All.

\n", "

A NOTER : vous pouvez travailler sur le tp (et tout autre fichier .ipynb) hors connexion en installant une version local du notebook de jupyter. Il faut que votre machine possède un interpreteur de python et que vous soyez connecter à internet.\n", "

    \n", "
  1. Lancer un terminal
  2. \n", "
  3. Taper la commande suivante : pip install jupyterlab
  4. \n", "
  5. Une fois l'installation terminée portez votre attention sur les dernières lignes affichées dans votre terminal vous invitant probablement à taper une ligne de commande pour faire une mise à jour
  6. \n", "
  7. Pour lancer notebook de jupyter, taper dans votre termial : jupyter notebook
  8. \n", "
  9. Votre simulateur de serveur est lancé. Il ne faut pas fermer votre terminal, auquel cas votre simulateur de serveur s'interompera. Suivez le lien indiqué dans les dernières lignes de votre terminal pour vous diriger vers votre espace local. L'interface se présente comme celle que vous trouverez sur le web. Votre travail sera cependant toujours enregistré et jamais perdu même si vous le consultez après plusieurs jours
  10. \n", "
\n", "

\n", "
\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", " Partie 0 : OutilsCrypto.py\n", "
\n", "

\n", "

\n", " Menu de navigation\n", " \n", "
\n", "

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Une bibliothèque regroupant quelques outils de la cryptologie vous ont été donnée. Chargeons l'intégralité des fonctionnalités qu'elle propose

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from OutilsCrypto import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

codex

\n", "

Cette fonction applique, comme en cours, le codex pédagogique base de notre étude : le caractère $\\texttt{A}$ est transformé en $0$, le $\\texttt{B}$ en 1 etcaetera jusqu'au $\\texttt{Z}$ qui est transformé en $25$. Exécuter la case suivante pour vous assurer du fonctionnement de cette fonction. Si le caractère n'est pas une lettre entre $\\texttt{A}$ et $\\texttt{Z}$, quel code erreur renverra la fonction ? Que dire de la case ?

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x='a'\n", "print(x, \"=\", codex(x))\n", "x='B'\n", "print(x, \"=\", codex(x))\n", "x='c'\n", "print(x, \"=\", codex(x))\n", "x='Z'\n", "print(x, \"=\", codex(x))\n", "x='9'\n", "print(x, \"=\", codex(x))\n", "x='('\n", "print(x, \"=\", codex(x))\n", "x='-'\n", "print(x, \"=\", codex(x))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

xedoc

\n", "

Cette fonction applique, comme en cours, le codex pédagogique inversé (il s'agit du mot codex à l'envers) : le nombre $25$ renvoie le caractète $\\texttt{Z}$, le chiffre $4$ renvoie le caractère $\\texttt{E}$ etcaetera. Si le nombre n'est pas entre $0$ et $25$, quel code erreur renverra la fonction ? Que dire de la case ?

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "n=0\n", "print(n, \"=\", xedoc(n))\n", "n=1\n", "print(n, \"=\", xedoc(n))\n", "n=4\n", "print(n, \"=\", xedoc(n))\n", "n=25\n", "print(n, \"=\", xedoc(n))\n", "n=26\n", "print(n, \"=\", xedoc(n))\n", "n=50\n", "print(n, \"=\", xedoc(n))\n", "n=-1\n", "print(n, \"=\", xedoc(n))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

paquet

\n", "

Cette fonction prend une chaine de caractère txt et un entier paq et vas convertir la chaine en un tableau d'entier correspondant aux paquets de lettre de taille paq. Les paquet seront complété par des $0$ si la longueur de la chaine txt n'est pas multiple de paq. Executer la case suivante pour observer le comportement de cette fonction. Cette fonction renvoie en particulier le tableau vide en cas d'erreur

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "txt=\"ABCD\"\n", "print(\"Sans taille de paquet :\", paquet(txt))\n", "print(\"Par paquet de 1 :\", paquet(txt, 1))\n", "print(\"Par paquet de 2 :\", paquet(txt, 2))\n", "print(\"Par paquet de 3 :\", paquet(txt, 3))\n", "txt=\"BONJOUR\"\n", "print(\"Par paquet de 2 :\", paquet(txt, 2))\n", "txt=\"Bonjour\"\n", "print(\"Par paquet de 2 :\", paquet(txt, 2))\n", "txt=\"Ca va ?\"\n", "print(\"Par paquet de 2 :\", paquet(txt, 2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Filtre

\n", "

Cette fonction prend en paramètre une chaine de caractère et renvoie la même chaine où les caractères spéciaux ou accentués ont été transformé en leur forme génériques (les accents disparaissent). Les espaces et la ponctuation sont enlevés

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "txt=\"Bonjour\"\n", "print(Filtre(txt))\n", "txt=\"Bonjour ca va ?\"\n", "print(Filtre(txt))\n", "txt=\"Tu me donnes ton 06 stp ?\"\n", "print(Filtre(txt))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

mod2base

\n", "

Cette fonction prend en paramètre un entier correspondant à la taille des paquets et renvoie le modulo de base de travail.

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(mod2base())\n", "print(mod2base(1))\n", "print(mod2base(2))\n", "print(mod2base(3))\n", "\n", "print(mod2base(-1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", " Partie 1 : Chiffrement de César\n", "
\n", "\n", "

\n", "

\n", " Menu de navigation\n", " \n", "
\n", "

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Ecrire la fonction Ecesar(txt, clef, paq=1) qui a deux paramètres obligatoire et un paramètre optionnel:\n", "

\n", "Cette fonction renvoie une chaine de caractère correspondant au chiffrement de César txt de clef clef par paquet de paq. Si paq vaut 1 alors la fonction devra retourner le décodage des entiers calculer. Sinon la fonction renverra une chaine de caractère correspondant aux entiers chiffrés du message séparé par des $\\texttt{-}$.
\n", "Par exemple le message $\\texttt{BONJOUR}$ de clef $3$ par paquet de 1 donne $\\texttt{ERQMRXU}$ alors que par paquet de 2, la fonction renvoie $\\texttt{117-1312-1423-1703}$.
\n", "\n", "La fonction renvoie la chaine vide (ie $\\texttt{\"\"}$) en cas d'erreur.\n", "

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def Ecesar(txt, clef, paq=1) :\n", " return \"\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Tests

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "txt=\"BONJOUR\"\n", "clef=3\n", "print(\"Par paquet de 1 :\", Ecesar(txt, clef))#ERQMRXU\n", "print(\"Par paquet de 2 :\", Ecesar(txt, clef, 2))#117-1312-1423-1703\n", "txt=\"Il était une fois...\"\n", "clef=2020\n", "print(\"Par paquet de 2 :\", Ecesar(txt, clef, 2))#\n", "print(\"Par paquet de 2 :\", Ecesar(Filtre(txt), clef, 2))#305-2439-2028-1414-798-8-312" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Ecrire la fonction Dcesar(txt, clef, paq=1) qui a deux paramètres obligatoire et un paramètre optionnel:\n", "

\n", "Cette fonction renvoie une chaine de caractère correspondant au déchiffrement de César txt de clef clef par paquet de paq.
\n", "ATTENTION : si paq vaut 1 alors txt est une suite de lettre de l'alphabet. Sinon cette chaine est une suite d'entiers séparés par des $\\texttt{-}$. On pourra récupérer une liste de chaine de caractère des entiers par txt.split('-')
\n", "La fonction renvoie la chaine vide (ie $\\texttt{\"\"}$) en cas d'erreur.\n", "

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def Dcesar(txt, clef, paq=1) :\n", " return \"\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Tests

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#Test 1\n", "txt0=\"BONJOUR\"\n", "clef=random.randint(0,25)\n", "txt1=Ecesar(txt0, clef)\n", "txt2=Dcesar(txt1, clef)\n", "print(txt0)\n", "print(txt1)\n", "print(txt2)#Doit redonner txt0\n", "\n", "#Test 2\n", "txt=\"La vie n'est pas un long fleuve tranquille !\"\n", "txt0=Filtre(txt)\n", "clef=random.randint(0,252525)\n", "txt1=Ecesar(txt0, clef, 3)\n", "txt2=Dcesar(txt1, clef, 3)\n", "print(txt)\n", "print(txt0)\n", "print(txt1)\n", "print(txt2)#Doit redonner txt0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", " Partie 2 : Brute force\n", "
\n", "\n", "

\n", "

\n", " Menu de navigation\n", " \n", "
\n", "

\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Dans cette dernière partie, on cherche à déchiffrer le messaque suivant :
\n", "$$\\texttt{2138-523-1651-1650-712-1434-1834-2338-412-721-212-708}$$ \n", "

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "MESSAGE = \"2138-523-1651-1650-712-1434-1834-2338-412-721-212-708\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Ecrire une procédure BruteForceCesar(txt, paq=1) qui teste toutes les clefs possible et affiche, lorsque le message à pu etre décrypter, la liste des déchiffrement possibles.

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def BruteForceCesar(txt, paq=1) : \n", " try : \n", " txt=str(txt)\n", " paq=int(paq)\n", " except :\n", " print(\"L'attaque ne fonctionne pas\")\n", " return\n", "\n", " clef_valide=0\n", " \n", " print(\"---------------------------------\")\n", " print(\"Début de l'attaque en froce brute\")\n", " print(\"---------------------------------\")\n", " \n", " top=time.time()\n", " \n", " #Mettre votre code ici\n", " \n", " temps=time.time()-top\n", " print(\"Fin de l'attaque | \"+str(clef_valide)+\" clefs valides testées (\"+str(round(temps,3))+\"s)\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Tests

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "txt0=\"BONJOUR\"\n", "txt1=Ecesar(txt0, random.randint(0,25))\n", "BruteForceCesar(txt1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Attaque de MESSAGE

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "BruteForceCesar(MESSAGE, 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

En observant la liste précédente vous pourrez lire le message décrypter... mais...

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", " Partie 3 : Brute force avec dictionnaire\n", "
\n", "

\n", "

\n", " Menu de navigation\n", " \n", "
\n", "

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

L'inconvenient avec la brute force est qu'il faut lire le message claire dans la liste des messages possible. Une alternative à ce travail de fourmis est d'analyser les messages déchiffrer et de déterminer lequel à le nombre de mot le plus élévé. Pour y arriver on va charger des dictionnaires. Exécuter le code suivant pour charger les différents dictionnaires proposée. ATTENTION : Cette opération peux prendre plusieurs secondes (environ 30). Un message de fin s'affichera lorsque le chargement sera terminé.

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"-----> DéBUT DU CHARGMENT DES DICTIONNAIRES <-----\")\n", "top=time.time()\n", "lang=\"FR\"\n", "print(\"CHARGEMENT DU DICTIONNAIRE \\\"\", lang, \"\\\": \\tEN COURS\",end='')\n", "DICO_FR = MonDico(lang)\n", "print(\"\\rCHARGEMENT DU DICTIONNAIRE \\\"\", lang, \"\\\": \\tTERMINéE (en\", round(time.time()-top, 3), \"secondes)\")\n", "top=time.time()\n", "lang=\"ANG\"\n", "print(\"CHARGEMENT DU DICTIONNAIRE \\\"\", lang, \"\\\": \\tEN COURS\",end='')\n", "DICO_ANG = MonDico(lang)\n", "print(\"\\rCHARGEMENT DU DICTIONNAIRE \\\"\", lang, \"\\\": \\tTERMINéE (en\", round(time.time()-top, 3), \"secondes)\")\n", "top=time.time()\n", "lang=\"ESP\"\n", "print(\"CHARGEMENT DU DICTIONNAIRE \\\"\", lang, \"\\\": \\tEN COURS\",end='')\n", "DICO_ESP = MonDico(lang)\n", "print(\"\\rCHARGEMENT DU DICTIONNAIRE \\\"\", lang, \"\\\": \\tTERMINéE (en\", round(time.time()-top, 3), \"secondes)\")\n", "top=time.time()\n", "lang=\"IT\"\n", "print(\"CHARGEMENT DU DICTIONNAIRE \\\"\", lang, \"\\\": \\tEN COURS\",end='')\n", "DICO_IT = MonDico(lang)\n", "print(\"\\rCHARGEMENT DU DICTIONNAIRE \\\"\", lang, \"\\\": \\tTERMINéE (en\", round(time.time()-top, 3), \"secondes)\")\n", "print(\"-----> FIN DU CHARGMENT DES DICTIONNAIRES <-----\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

La fonction pertinence

\n", "

\n", "Cette fonction prend deux paramètres : \n", "

\n", " Cette fonction retourne un entier correspondant au nombre de mot du dictionnaire reconnu dans la phrase.
\n", " Par exemple dans le mot $\\texttt{BONJOUR}$ sont reconnus cinq mots du dictionnaire français : $\\texttt{BON}$, $\\texttt{ON}$, $\\texttt{JOUR}$, $\\texttt{OU}$ et $\\texttt{BONJOUR}$\n", "

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(pertinence(\"BONJOUR\", DICO_FR))#5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Il en va de même en changeant la langue, qui doit être une donnée a priori et non a posteriori, comme le montre le contre-exemple.

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "txt=\"BONJOUR\"\n", "print(\"Pertinance FR :\", pertinence(txt, DICO_FR))\n", "print(\"Pertinance ANG :\", pertinence(txt, DICO_ANG))\n", "print(\"Pertinance ESP :\", pertinence(txt, DICO_ESP))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Ecrire une procédure BruteForceCesar_dico qui prend en paramètre : \n", "

\n", "Comme son homonyme cette procédure réalise une attaque mais n'affiche que des chaines décryptées de plus en plus pertinente.\n", "

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def BruteForceCesar_dico(txt, paq=1, dico=DICO_FR) : \n", " try : \n", " txt=str(txt)\n", " paq=int(paq)\n", " except :\n", " print(\"L'attaque ne fonctionne pas\")\n", " return\n", "\n", " clef_valide=0\n", "\n", " print(\"\\t-----------------------------\")\n", " print(\"\\tBRUTE FORCE AVEC DICTIONNAIRE\")\n", " print(\"\\t-----------------------------\")\n", " \n", " top=time.time()\n", " \n", " #Mettre votre code ici\n", " \n", " temps=time.time()-top\n", " print(\"Le dernier message semble être le bon\")\n", " print(str(clef_valide)+\" clefs valides ont été testées\")\n", " print(\"Attaque terminée (\"+str(round(temps, 3))+\"s)\")\n", " print(\"---------------------------------\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Tests

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "txt0=Filtre(\"My name is David. I'd like to have student who work\")\n", "for paq in [1, 2, 3] : \n", " print(\"Par paquet de\", paq)\n", " txt1=Ecesar(txt0, random.randint(0, mod2base(paq)-1), paq)\n", " print(\"Message à attaquer :\", txt1)\n", " BruteForceCesar_dico(txt1, paq, DICO_ANG)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Attaque de MESSAGE

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "BruteForceCesar_dico(MESSAGE, 2, DICO_FR)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Attaque final

\n", "

Un chiffrement de César à été utilisé et le message obtenu est le suivant. Attaquez le et donner le nom de la personne qui a prononcé cette phrase à votre enseignant pour obtenir un bonus !\n", "$$\\texttt{62358-63351-235870-63054-124260-52854-43841}$$\n", "

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "MESSAGE2 = \"62358-63351-235870-63054-124260-52854-43841\"\n", "BruteForceCesar_dico(MESSAGE2, 3, DICO_ANG)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Fini en avance ?

\n", "

Le MESSAGE3 n'est pas nécessairement en français. Bon chance.

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "MESSAGE3=\"20130913-20170903-18041699-8181103-12040810-11042016-3170417-18042016-9041203-1001918-17000817-18001317-17041507-18999999\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.0" } }, "nbformat": 4, "nbformat_minor": 2 }